package com.vhall.component.plugin.common.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;

import java.io.UnsupportedEncodingException;
import java.util.Date;

/**
 * @author yongzheng.xu
 * @date 2021/6/20 19:32
 */
@Slf4j
public class JWTUtil {

    private JWTUtil() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 设置过期时间24小时
     */
    private static final long EXPIRE_TIME = 1000 * 60 * 60 * 24L;

    private static final String USERNAME = "username";

    /**
     * 设置密钥
     */
    @Value("${vhall.vss.jwt-secret:n0secret}")
    private static String secret;

    /**
     * 根据用户名创建一个token
     *
     * @param username 用户名
     * @return 返回的token字符串
     */
    public static String createToken(String username) {
        try {
            //将当前时间的毫秒数和设置的过期时间相加生成一个新的时间
            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            //由密钥创建一个指定的算法
            Algorithm algorithm = Algorithm.HMAC256(secret);
            return JWT.create()
                    //附带username信息
                    .withClaim(USERNAME, username)
                    //附带过期时间
                    .withExpiresAt(date)
                    //使用指定的算法进行签名
                    .sign(algorithm);
        } catch (UnsupportedEncodingException e) {
            log.error("", e);
            return null;
        }
    }

    /**
     * 验证token是否正确
     *
     * @param token    前端传过来的token
     * @param username 用户名
     * @return 返回boolean
     */
    public static boolean verify(String token, String username) {
        try {
            //获取算法
            Algorithm algorithm = Algorithm.HMAC256(secret);
            //生成JWTVerifier
            JWTVerifier verifier = JWT.require(algorithm).withClaim(USERNAME, username).build();
            //验证token
            verifier.verify(token);
            return true;
        } catch (UnsupportedEncodingException | TokenExpiredException e) {
            log.error("", e);
            return false;
        }
    }

    /**
     * 从token中获得username，无需secret
     *
     * @param token token
     * @return username
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(USERNAME).asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }
}
